﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using DevExpress.Xpf.Bars;
using Moonlite.ExtensionApi;
using Moonlite.ExtensionApi.ControlInterfaces;
using Moonlite.ExtensionApi.GlobalInterfaces;
using Moonlite.Platform.General;
using Moonlite.Platform.Project;
namespace Moonlite.Controls {
    public partial class FunctionExplorer : UserControl, IFunctionExplorer {
        private const string ConnectionString = "data source=\"Data\\GalaxyNatives.db\"";
        private SQLiteConnection connection = new SQLiteConnection(ConnectionString);
        public static JassCodeObjectCollection JassNativeCode { get; private set; }
        public static GalaxyCodeObjectCollection GalaxyNativeCode { get; private set; }
        public List<object> Items {
            get {
                List<object> items = new List<object>();
                foreach (object item in listBox.Items) {
                    items.Add(item);
                }
                return items;
            }
        }
        private void Search() {
            try {
                if (Global.Instance != null && Global.Instance.Project != null) {
                    if (Global.Instance.Project.Type == ProjectType.Jass) {
                        listBox.SelectedIndex = -1;
                        listBox.SelectionMode = SelectionMode.Extended;
                        List<object> newItems = new List<object>();
                        List<object> removedItems = new List<object>();
                        object item = null;
                        if (searchBox.EditValue == null || ((string)searchBox.EditValue).Length == 0) {
                            return;
                        }
                        do {
                            item = listBox.FindName((string)searchBox.Content);
                            listBox.SelectedItems.Add(item);
                            listBox.Items.Remove(item);
                            removedItems.Add(item);
                            if (newItems.Contains(item) == false) {
                                newItems.Add(item);
                            }
                        } while (item != null);
                        removedItems.ForEach(removedItem => {
                            listBox.Items.Add(removedItem);
                        });
                        newItems.ForEach(newItem => {
                            listBox.Items.Remove(newItem);
                            listBox.Items.Insert(0, newItem);
                        });
                        listBox.SelectedIndex = 0;
                    }
                    else if (Global.Instance.Project.Type == ProjectType.Galaxy) {
                        listBox.Items.Clear();
                        SQLiteCommand command = null;
                        if (string.IsNullOrEmpty(((string)searchBox.EditValue))) {
                            command = new SQLiteCommand("SELECT * FROM elements ORDER BY Name", connection);
                        }
                        else {
                            string search = (string)searchBox.EditValue;
                            search = search.Replace("@", "@@");
                            search = search.Replace("_", "@_");
                            search = search.Replace("'", "\"");
                            command = new SQLiteCommand("SELECT * FROM elements WHERE name LIKE '%" + search + "%' ESCAPE '@' ORDER BY name", connection);
                        }
                        if (command != null) {
                            SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                            DataTable dataTable = new DataTable("elements");
                            adapter.Fill(dataTable);
                            foreach (DataRow row in dataTable.Rows) {
                                GalaxyCodeObject @object = new GalaxyCodeObject();
                                @object.Code = (string)row.ItemArray[1];
                                @object.Name = (string)row.ItemArray[0];
                                switch ((string)row.ItemArray[5]) {
                                    case "native":
                                        @object.Type = GalaxyCodeObjectType.Native;
                                        break;
                                    case "function":
                                        @object.Type = GalaxyCodeObjectType.Function;
                                        break;
                                    case "global":
                                    case "constant":
                                        @object.Type = GalaxyCodeObjectType.Variable;
                                        break;
                                }
                                listBox.Items.Add(@object);
                            }
                        }
                    }
                }
            }
            catch (Exception exception) {
                Logger.Log += exception.Message;
            }
        }
        private void OnSearchBoxEditValueChanged(object sender, RoutedEventArgs e) {
            Search();
        }
        private void OnSearchItemClick(object sender, ItemClickEventArgs e) {
            Search();
        }
        private static int CompareJassCodeObjects(JassCodeObject a, JassCodeObject b) {
            if (a == null) {
                throw new ArgumentNullException("a");
            }
            if (b == null) {
                throw new ArgumentNullException("b");
            }
            return a.Name.CompareTo(b.Name);
        }
        private static int CompareGalaxyCodeObjects(GalaxyCodeObject a, GalaxyCodeObject b) {
            if (a == null) {
                throw new ArgumentNullException("a");
            }
            if (b == null) {
                throw new ArgumentNullException("b");
            }
            return a.Name.CompareTo(b.Name);
        }
        public void UpdateNativeCode() {
            listBox.Items.Clear();
            if (Global.Instance.Project.Type == ProjectType.Jass) {
                JassNativeCode.Sort(CompareJassCodeObjects);
                foreach (JassCodeObject @object in JassNativeCode) {
                    listBox.Items.Add(@object);
                }
            }
            else {
                SQLiteCommand command = new SQLiteCommand("SELECT * FROM elements ORDER BY Name", connection);
                SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                DataTable dataTable = new DataTable("elements");
                adapter.Fill(dataTable);
                foreach (DataRow row in dataTable.Rows) {
                    GalaxyCodeObject @object = new GalaxyCodeObject();
                    @object.Code = (string)row.ItemArray[1];
                    @object.Name = (string)row.ItemArray[0];
                    switch ((string)row.ItemArray[5]) {
                        case "native":
                            @object.Type = GalaxyCodeObjectType.Native;
                            break;
                        case "function":
                            @object.Type = GalaxyCodeObjectType.Function;
                            break;
                        case "global":
                        case "constant":
                            @object.Type = GalaxyCodeObjectType.Variable;
                            break;
                    }
                    listBox.Items.Add(@object);
                }
            }
        }
        private void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) {
            if (Global.Instance.Project != null && Global.Instance.Project.Type == ProjectType.Jass) {
                JassCodeObject codeObject = (JassCodeObject)listBox.SelectedItem;
                if (codeObject != null) {
                    ((ICodeExplorer)((object[])(Global.Instance.GetService(typeof(ICodeExplorer))))[0]).SetCode(codeObject.Code);
                }
            }
            else {
                GalaxyCodeObject codeObject = (GalaxyCodeObject)listBox.SelectedItem;
                if (codeObject != null) {
                    ((ICodeExplorer)((object[])(Global.Instance.GetService(typeof(ICodeExplorer))))[0]).SetCode(codeObject.Code);
                }
            }
        }
        public static void ReadNativeCode() {
            JassNativeCode = JassNativeCodeReader.Read();
            GalaxyNativeCode = GalaxyNativeCodeReader.Read();
        }
        public void OpenConnection() {
            connection.Open();
        }
        public void Clear() {
            listBox.Items.Clear();
        }
        public FunctionExplorer() {
            InitializeComponent();
            try { Global.Instance.RegisterService(this, GetType().GetInterface("IFunctionExplorer")); }
            catch { }
        }
    }
}
